﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace SurvivalStrategy.Modules
{
    public enum BehaviorTags
    {
        Standard,
        Working,
        Fighting,
        Resting
    }
    //klasa abstrakcyjna, po ktorej dziedzicza wszystkie behavior module
    public abstract class BehaviorModule
    {
        private List<BahaviorModuleFunction> moduleFunctions;
        public List<BahaviorModuleFunction> ModuleFunctions { get { return moduleFunctions; } }
        private static EntitiesManager entitiesManager;
        private static World world;
        private int id = -1;
        private EntityController controller;

        public BehaviorModule()
        {
            moduleFunctions = new List<BahaviorModuleFunction>();
        }
        
        protected void AddFunction(BehaviroModuleFunc actionModuleFunction, BehaviroModulePriority actionModulePriority, BehaviorTags tag)
        {
            moduleFunctions.Add(new BahaviorModuleFunction(actionModuleFunction, actionModulePriority, tag));
        }

        public static void SetValues(SurvivalStrategy.EntitiesManager eManager)
        {
            if (entitiesManager == null)
                entitiesManager = eManager;
        }

        public static void SetWorld(World w)
        {
            if (world == null)
                world = w;
        }

        public void SetID(int id)
        {
            if(this.id == -1)
                this.id = id;
        }

        public int GetID()
        {
            return this.id;
        }

        public void SetController(EntityController controller)
        {
            this.controller = controller;
        }

        protected virtual void SendRequest(int senderID, int recieverID, ActionTags tag, ActionModuleArgs args, int priority, int lifeSpan)    //wysyla zlecenie
        {
            controller.SendRequest(senderID, recieverID, tag, args, priority, lifeSpan);
        }

        protected virtual void SendRequest(int senderID, int recieverID, ActionTags tag, ActionModuleArgs args)    //wysyla zlecenie
        {
            controller.SendRequest(senderID, recieverID, tag, args);
        }

        #region GetValuesFromID
        protected Vector3 GetPosition(int id)
        {
            return entitiesManager.GetEntity(id).WorldInfo.Position;
        }

        protected Vector3 GetForwardVector(int id)
        {
            return entitiesManager.GetEntity(id).WorldInfo.Forward;
        }

        protected int GetAppearance(int id)
        {
            return entitiesManager.GetEntity(id).WorldInfo.Appearance;
        }

        protected string GetName(int id)
        {
            return entitiesManager.GetEntity(id).WorldInfo.Name;
        }

        protected Attributes GetAttributes(int id)
        {
            return entitiesManager.GetEntity(id).WorldInfo.PersonalAttributes;
        }
        #endregion
        #region GetValues
        protected Vector3 GetPosition()
        {
            return entitiesManager.GetEntity(this.id).WorldInfo.Position;
        }

        protected Vector3 GetForwardVector()
        {
            return entitiesManager.GetEntity(this.id).WorldInfo.Forward;
        }

        protected int GetAppearance()
        {
            return entitiesManager.GetEntity(this.id).WorldInfo.Appearance;
        }

        protected string GetName()
        {
            return entitiesManager.GetEntity(this.id).WorldInfo.Name;
        }

        protected Attributes GetAttributes()
        {
            return entitiesManager.GetEntity(this.id).WorldInfo.PersonalAttributes;
        }
        #endregion
        #region SetValues
        public void SetSetName(string name)
        {
            entitiesManager.GetEntity(this.id).WorldInfo.Name = name;
        }

        public void SetPosition(Vector3 position)
        {
            entitiesManager.GetEntity(this.id).WorldInfo.Position = position;
        }

        public void SetForward(Vector3 forward)
        {
            entitiesManager.GetEntity(this.id).WorldInfo.Forward = forward;
        }

        public void SetAppearance(int appearance)
        {
            entitiesManager.GetEntity(this.id).WorldInfo.Appearance = appearance;
        }
        #endregion
        #region Memory
        protected Memory.MemorySegment GetMemoryValue(string key)        //pobiera wartosc z pamieci o podanej nazwie
        {
            if (entitiesManager.GetEntity(this.id).Memory.ContainsKey(key))
                return entitiesManager.GetEntity(this.id).Memory[key];
            else return null;
        }

        protected bool SetMemoryValueInNone(string key, Memory.MemorySegment segment)  //ustawia wartosc do pamieci pod podana nazwe, tylko jezeli jeszcze takiej nie uzyl
        {
            if (!entitiesManager.GetEntity(this.id).Memory.ContainsKey(key))
            {
                entitiesManager.GetEntity(this.id).Memory.Add(key, segment);
                return true;
            }
            else return false;
        }

        protected void SetForceMemoryValue(string key, Memory.MemorySegment segment)  //ustawia wartosc do pamieci pod podana nazwe, jezeli juz istnieje taki klucz, podmienia wartosc
        {
            if (!entitiesManager.GetEntity(this.id).Memory.ContainsKey(key))
            {
                entitiesManager.GetEntity(this.id).Memory.Add(key, segment);
            }
            else entitiesManager.GetEntity(this.id).Memory[key] = segment;
        }

        protected bool ForceSetMemoryValue(string key, Memory.MemorySegment segment)  //sprawdza czy podana klucz juz istnieje
        {
            return entitiesManager.GetEntity(this.id).Memory.ContainsKey(key);
        }

        protected void RemoveMemoryValue(string key)  //usuwa dany klucz
        {
            if (entitiesManager.GetEntity(this.id).Memory.ContainsKey(key))
                entitiesManager.GetEntity(this.id).Memory.Remove(key);
        }
        #endregion

        public T GetComponent<T>() where T : Entities.EnitityComponents.EntitiyComponent
        {
            return entitiesManager.GetEntity(this.id).GetComponent<T>();
        }

        public T GetComponent<T>(int id) where T : Entities.EnitityComponents.EntitiyComponent
        {
            return entitiesManager.GetEntity(id).GetComponent<T>();
        }

        public List<WorldData.WorldElement> GetWorldElementAbsolutePosition(Vector3 position)   //bierze element z danego pola
        {
            return world.GetPositionsElements(position);
        }

        public List<WorldData.WorldElement> GetWorldElementRelativePosition(Vector3 position)   //bierze element w odleglosci o jakas od naszej
        {
            return world.GetPositionsElements(Vector3.Add(GetPosition(), position));
        }

        public WorldData.Colliders.Collider GetCollider()   //bierze element w odleglosci o jakas od naszej
        {
            return entitiesManager.GetEntity(id).GetComponent<Entities.EnitityComponents.EntitiyCollider>().Collider;
        }
    }
}
